package com.forgenet.game.module.player.manager;

import com.forgenet.game.module.player.Player;
import com.sparrow.redis.cache.mongo.RedisMongoCache;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class PlayerManager extends RedisMongoCache<Long, Player> {
    private final ConcurrentHashMap<Long, Player> players = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, Long> accountToPlayerIds = new ConcurrentHashMap<>();

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private MongoTemplate mongoTemplate;

    private static final String PLAYER_CACHE_PREFIX = "player:";

    public void save(Player player) {
        super.save(player);
        accountToPlayerIds.remove(player.getAccount());
    }

    public void insert(Player player) {
        super.insert(player);
        accountToPlayerIds.put(player.getAccount(), player.getPlayerId());
        RMap<String, Long> accountMap = redissonClient.getMap("account:playerId");
        accountMap.put(player.getAccount(), player.getPlayerId());
    }

    public void register(Player player) {
        super.register(player);
        accountToPlayerIds.put(player.getAccount(), player.getPlayerId());
    }

    public Long getPlayerIdByAccount(String account) {
        // 1. 本地缓存
        Long playerId = accountToPlayerIds.get(account);
        if (playerId != null) {
            return playerId;
        }
        // 2. Redis 缓存
        RMap<String, Long> accountMap = redissonClient.getMap("account:playerId");
        playerId = accountMap.get(account);
        if (playerId != null) {
            accountToPlayerIds.put(account, playerId); // 回填本地缓存
            return playerId;
        }
        // 3. MongoDB 回源
        Query query = new Query(Criteria.where("account").is(account));
        query.fields().include("playerId");
        Player player = mongoTemplate.findOne(query, Player.class);
        if (player != null && player.getPlayerId() != null) {
            playerId = player.getPlayerId();
            // 回填 Redis 和本地缓存
            accountMap.put(account, playerId);
            accountToPlayerIds.put(account, playerId);
            return playerId;
        }
        return null;
    }


    public boolean isOnline(long playerId) {
        return players.containsKey(playerId);
    }

    public Collection<Player> getAllPlayers() {
        return players.values();
    }

    public int onlineCount() {
        return players.size();
    }

    @Override
    protected String getRedisKeyPrefix() {
        return PLAYER_CACHE_PREFIX;
    }

}

